package agents;

import java.util.Hashtable;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.InitialContext;

import model.ACLMessage;
import model.AgentInfo;
import model.Host;

public abstract class Agent {

	protected MessageProducer msgProducer;
	protected AgentInfo agentInfo;
	protected Connection connection;
	protected Session session;
	protected MessageProducer producer;
    protected Topic topic;
	protected ObjectMessage msg;
	
	private static int createdAgents=0;
	
	public Agent() {
		agentInfo=new AgentInfo();
		agentInfo.setAID(createdAgents++);
		System.out.println("Created agent: "+agentInfo);	
	}
	
	public Agent(Host localHost) {
		agentInfo=new AgentInfo();
		agentInfo.setLocalHost(localHost);
		agentInfo.setAID(createdAgents++);
		System.out.println("Created agent: "+agentInfo);
	}
	
	public Agent(AgentInfo agentInfo) {
		this.agentInfo=agentInfo;
		System.out.println("Created agent: "+agentInfo);
	}
	
    public void processMessage(ACLMessage message) {
    	System.out.println("Agent: " +agentInfo+" recieved the message: "+message.toString());
    }
    
    protected void sendMessage(ACLMessage message) {
    	// create and publish a message
		try {
			connectToServer();
			msg=session.createObjectMessage();
			msg.setObject(message);
			producer.send(msg);
			finalize();
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			System.err.println("Failed to send message. JMS error.");
		}
    }

	public AgentInfo getAgentInfo() {
		return agentInfo;
	}

	public void setAgentInfo(AgentInfo agentInfo) {
		this.agentInfo = agentInfo;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((agentInfo == null) ? 0 : agentInfo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Agent other = (Agent) obj;
		if (agentInfo == null) {
			if (other.agentInfo != null)
				return false;
		} else if (!agentInfo.equals(other.agentInfo))
			return false;
		return true;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return agentInfo.toString();
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected void connectToServer() {
		try {
			Hashtable jndiProps = new Hashtable();
		    jndiProps.put("java.naming.factory.initial", "org.jboss.as.naming.InitialContextFactory");
			Context context = new InitialContext(jndiProps);
			ConnectionFactory cf = (ConnectionFactory) context
					.lookup("/ConnectionFactory");
			
			topic = (Topic) context
					.lookup("topic/mojTopic2");
					
			context.close();
			connection = cf.createConnection("guest", "guestguest");
			session = connection.createSession(false,
					Session.AUTO_ACKNOWLEDGE);

			connection.start();
			producer=session.createProducer(topic);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	@Override
	public void finalize() {
		try {
			producer.close();
			connection.close();
			session.close();
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			System.err.println("Closing of connection unsucsessful.");
		}
	}
}
